$(function () {
    //dom列表
    var doms = {
        quesionTextArea: "#quesion-text",
        sendBtn: "#send-btn",
        clearBtn: "#clear-btn",
        tpl_aiMsg: "#tpl-aiMsg", //消息模板
        tpl_userMsg: "#tpl-userMsg",
        tpl_timeMsg: "#tpl-timeMsg",
        tpl_character: "#tpl-character", //好友项模板
        tpl_chatpanel: "#tpl-chatpanel", //会话面板模板
        chatpanel_list: "#chatpanel-list", //会话面板列表
        aiName: "#aiName",
        chatPanel: ".chat-view .chat-panel",
        backBtm: "#backbtm", //回到底部按钮
        version: "#version-value", //版本号
        characterList: "#character-list", //好友列表
        more_btn: "#more-btn", //更多按钮
        input_remlen: "#input-remlen", //输入框剩余长度
        input_maxlen: "#input-maxlen", //输入框最大长度
        copyRight: "#copy-right", //版权信息
    };

    for (var key in doms) {
        if (typeof doms[key] == "string") {
            doms[key] = $(doms[key]);
        }
    }

    //页面配置
    var config = {
        maxChatCount: 20, //最大会话数量
        markdownFlavor: "github", //markdown 解析主题
        timeMsgInsertMinInterval: 5, //时间消息插入最小间隔，单位：分钟
        autoSaveMsg: true, //是否自动保存消息
    };

    //markdown 解析器初始化
    showdown.setFlavor(config.markdownFlavor);
    var mdConverter = new showdown.Converter();

    //上下文
    var context = {
        onRedy: false, //是否准备好
        lastTime: new Date(), //最后刷新时间
        aiName: "小白猿", //ai名称
        version: "1.1.0", //版本号
        maxQuesionLength: 1500, //最大问题长度
        /**
         * 角色列表
         * @type {Character[]}
         */
        characters: [], //角色列表
        activeCharacter: null, //当前角色id
        //设置活动角色
        setActiveCharacter: function (id) {
            var activeCharacter = this.findCharacterById(id);
            if (!activeCharacter) {
                activeCharacter = this.characters[0];
            }
            this.activeCharacter = activeCharacter;
            this.fireEvent("activeChange", activeCharacter);
        },
        //根据id查找角色
        findCharacterById: function (id) {
            var result = null;
            context.characters.forEach(function (item) {
                if (item.id == id) {
                    result = item;
                }
            });
            return result;
        },
        //初始化上下文
        loadContext: function (requestCallback) {
            var tis = this;
            $.ajax({
                url: "/api/ChatApi/GetChatContext",
                type: "get",
                dataType: "json",
                success: function (res) {
                    if (res.success) {
                        var data = res.data;
                        tis.aiName = data.aiName;
                        tis.version = data.version;
                        tis.maxQuesionLength = data.maxQuesionLength;
                        //将characters 转为 Character 对象
                        data.characters.forEach(function (item) {
                            var character = new Character(item);
                            tis.characters.push(character);
                        });
                        if (tis.characters.length == 0) {
                            console.error("角色列表为空");
                            return;
                        }
                    } else {
                        console.error(res.message);
                    }
                    requestCallback && requestCallback.call(tis, res);
                    tis.fireEvent("loadContext", res);
                },
            });
        },
        //加载页面
        loadPage: function (readyCallback) {
            doms.characterList.empty();
            doms.chatpanel_list.empty();
            context.characters.forEach(function (item) {
                //初始化好友列表
                var character_tpl = $(doms.tpl_character.html());
                //id
                character_tpl.attr("id", "character-" + item.id).attr("data-id", item.id);
                character_tpl.find(".head-img").attr("src", item.headSrc);
                character_tpl.find(".info-box .name").text(item.name);
                character_tpl.find(".info-box .desc").text(item.desc).attr("title", item.desc);
                doms.characterList.append(character_tpl);
                item.characterTarget = character_tpl[0];

                //绑定事件
                character_tpl.on("click", function () {
                    var id = $(this).attr("data-id");
                    $(this).addClass("active").siblings().removeClass("active");
                    chatpanel_tpl
                        .css({
                            "z-index": 1,
                            visibility: "visible",
                        })
                        .siblings()
                        .css({
                            "z-index": 0,
                            visibility: "hidden",
                        });
                    context.setActiveCharacter(id);
                    pager.chatBox.scrollBottom(id);
                });

                //初始化会话面板
                var chatpanel_tpl = $(doms.tpl_chatpanel.html());
                chatpanel_tpl.attr("id", "chat-box-" + item.id).attr("data-id", item.id);
                doms.chatpanel_list.append(chatpanel_tpl);
                item.chatBoxTarget = chatpanel_tpl[0];
                item.loadMessageFromLocal();
                //scrollChatpanel 滚动事件, 显示/隐藏回到底部按钮
                chatpanel_tpl.on("scroll", function () {
                    pager.chatBox.checkScrollBottomVisible(item.id);
                });
            });
            //默认第一个角色为当前角色
            doms.characterList.find(".character-item:first").trigger("click");

            //加载聊天记录
            context.characters.forEach(function (charer) {
                //遍历消息列表, 添加到页面
                charer.messageList.forEach(function (msgEnty) {
                    var msgDom = null;
                    if (msgEnty.from == 0) {
                        msgDom = pager.chatBox.ownerSend(charer.id, msgEnty, false, false);
                    } else if (msgEnty.from == 1) {
                        msgDom = pager.chatBox.otherSend(charer.id, msgEnty, false, false);
                    }

                    //失败的消息添加失败标识
                    if (msgEnty.fail === true && msgDom) {
                        tools.setMsgFail(msgDom, msgEnty.id);
                    }
                });

                //滚动到底部
                pager.chatBox.scrollBottom(charer.id);
            });

            //清理无效的会话记录
            var ids = context.characters.map(function (item) {
                return item.id;
            });
            Character.prototype.clearLocalMessage(ids);

            doms.version.text(context.version);
            doms.aiName.text(context.aiName);

            //版权信息
            var starYeard = parseInt("2023");
            var year = parseInt(new Date().getFullYear().toString());
            var cpy_format = starYeard + " - " + year;
            if (year == starYeard) {
                cpy_format = year;
            }
            doms.copyRight.text(`© Muihd ${cpy_format}`);

            context.onRedy = true;
            readyCallback && readyCallback.call(context);
            context.fireEvent("redy");
        },
    };

    //初始化上下文
    context.loadContext(function (res) {
        if (res.success) {
            context.loadPage();
        }
    });

    //工具类
    var tools = {
        //转义html标签
        escapeHtml: function escapeHtml(text) {
            var res = text.replace(/[<>&"]/g, function (match, pos, originalText) {
                switch (match) {
                    case "<":
                        return "&lt;";
                    case ">":
                        return "&gt;";
                    case "&":
                        return "&amp;";
                    case '"':
                        return "&quot;";
                }
            });
            //保留换行符插入
            res = res.replace(/\n/g, "<br/>");
            return res;
        },
        //检测html中包含的编程语言
        checkCodeLanguagesFromHtml: function checkCodeLanguagesFromHtml(markdownBody) {
            var codes = $(markdownBody).find("code");
            var result = [];
            codes.each(function (index, item) {
                var lang = $(item).attr("class");
                var reg = /language-(\w+)/;
                var match = reg.exec(lang);
                result.push({
                    dom: item,
                    lang: match && match[1] ? match[1] : "code",
                });
            });
            return result;
        },
        //检测插入时间气泡
        checkInsertTime: function checkInsertTime(id, time) {
            time = time || new Date();
            var interval = (time - context.lastTime) / 1000 / 60;
            if (interval > config.timeMsgInsertMinInterval) {
                pager.chatBox.insertTime(id, time);
                context.lastTime = time;
            }
        },
        //从数组中随机一个元素
        randomOne: function randomOne(arr) {
            if (!arr || arr.length == 0) return null;
            if (arr.length == 1) return arr[0];
            var index = Math.floor(Math.random() * arr.length);
            return arr[index];
        },
        //范围内随机一个整数
        randomInt: function randomInt(min, max) {
            return Math.floor(Math.random() * (max - min + 1) + min);
        },
        //拷贝 文本到剪贴板,支持换行,高兼容性
        copyText: function copyText(text) {
            if (!text) return;

            if (navigator.clipboard) {
                navigator.clipboard.writeText(text);
                return;
            }
            var copyDiv = document.createElement("div");
            copyDiv.style.position = "fixed";
            copyDiv.style.opacity = "0";
            copyDiv.id = "copyDiv";
            document.body.appendChild(copyDiv);

            //将text内容复制到div中,并将\n替换为<br>
            copyDiv.innerHTML = text.replace(/\n/g, "<br>");
            var range = document.createRange();
            range.selectNode(copyDiv);
            var selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
            document.execCommand("copy");
            selection.removeAllRanges();

            document.body.removeChild(copyDiv);
        },
        //时间格式化
        formatDate: function formatDate(time, format) {
            var t = new Date(time);
            var tf = function (i) {
                return (i < 10 ? "0" : "") + i;
            };
            return format.replace(/yyyy|MM|dd|HH|mm|ss/g, function (a) {
                switch (a) {
                    case "yyyy":
                        return tf(t.getFullYear());
                    case "MM":
                        return tf(t.getMonth() + 1);
                    case "mm":
                        return tf(t.getMinutes());
                    case "dd":
                        return tf(t.getDate());
                    case "HH":
                        return tf(t.getHours());
                    case "ss":
                        return tf(t.getSeconds());
                }
            });
        },
        //判断两个时间是否是同一天
        isSameDay: function isSameDay(time1, time2) {
            time1 = new Date(time1);
            time2 = new Date(time2);
            return time1.getFullYear() == time2.getFullYear() && time1.getMonth() == time2.getMonth() && time1.getDate() == time2.getDate();
        },
        //激活对象的事件处理能力
        setEventAbility: function translateEvent(...objs) {
            //if (typeof obj != "object") return;
            var eventFuncs = {
                //事件列表
                eventList: {},
                //触发事件
                fireEvent: function (tis, eventName, args) {
                    var _tis = tis;
                    var _eventName = eventName;
                    var _args = args;

                    if (typeof tis == "string" && typeof eventName == "object") {
                        _tis = this;
                        _args = eventName;
                        _eventName = tis;
                    }

                    var list = this.eventList[_eventName];
                    if (!list) return;
                    for (var i = 0; i < list.length; i++) {
                        list[i].call(_tis, _args);
                    }
                },
                //注册事件
                on: function (eventName, func) {
                    var list = this.eventList[eventName];
                    if (!list) {
                        list = [];
                        this.eventList[eventName] = list;
                    }
                    list.push(func);
                },
            };

            //绑定到 obj
            for (var i = 0; i < objs.length; i++) {
                Object.assign(objs[i], eventFuncs);
            }
        },
        //根据时间戳创建尽量短的唯一id
        nextId: function createId(time) {
            time = time || new Date();
            var id = time.getTime().toString(36);
            return id;
        },
        //将消息设置失败
        setMsgFail: function setMsgFail(msgDom, msgId) {
            if (!msgDom || !msgId) throw new Error("参数错误");
            var dot = $(`<div title="消息已发出，但是对方未收到，点击再次发送" data-msgid="${msgId}" class="fail-dot"></div>`);            
            $(msgDom).find(".bubble").append(dot);

            //点击再次发送
            $(dot).click(function () {
                var msg = $(this).parent().children(".msg-content").text();
                var character = context.activeCharacter;
                pager.chatBox.ownerSend(character.id,msg);
            });
        }
    };

    //页面操作器
    var pager = {
        //输入框操作
        quesionInput: {
            //获取输入框内容
            getText: function () {
                return doms.quesionTextArea.val();
            },
            //设置输入框内容
            setText: function (text) {
                doms.quesionTextArea.val(text);
            },
            //清空输入框内容
            clear: function () {
                doms.quesionTextArea.val("");
                this.calcRemLength();
            },
            //统计输入框内容长度
            calcRemLength: function () {
                //忽略换行和空格
                var currerLen = $(doms.quesionTextArea).val().replace(/\n/g, "").replace(/\s/g, "").length;
                var maxLen = context.maxQuesionLength;
                doms.input_remlen.text(currerLen);
                if (currerLen > maxLen) {
                    doms.input_remlen.css({
                        color: "red",
                    });
                } else {
                    doms.input_remlen.css({
                        color: "#999",
                    });
                }
            }
        },
        //对话框操作
        chatBox: {
            //获取当前对话框
            getActiveChatBox: function () {
                return $(context.activeCharacter.chatBoxTarget).children(".chat-box");
            },
            //获取对话框
            getChatBox: function (id) {
                return $(context.findCharacterById(id).chatBoxTarget).children(".chat-box");
            },
            //滚动到底部
            scrollBottom: function (id) {
                var scrollChatpanel = this.getChatBox(id).parent();
                scrollChatpanel.scrollTop(scrollChatpanel[0].scrollHeight);
                doms.backBtm.hide();
            },
            //判断是否已经滚动到了底部
            isScrollBottom: function (id) {
                var scrollChatpanel = this.getChatBox(id).parent();
                var scrollHeight = scrollChatpanel[0].scrollHeight;
                var scrollTop = scrollChatpanel.scrollTop();
                var height = scrollChatpanel.height();
                return scrollHeight - scrollTop - height < 10;
            },
            //判断是否需要显示滚动到底部按钮
            checkScrollBottomVisible: function (id) {
                var isbtm = pager.chatBox.isScrollBottom(id);
                if (isbtm) {
                    doms.backBtm.hide();
                } else {
                    doms.backBtm.show();
                }
            },
            //删除超出最大会话数量的会话
            checkRemove: function (id) {
                //TODO: 替换 doms.chatBox
                var chatBox = this.getChatBox(id);
                if (config.maxChatCount <= 0) return;
                let count = chatBox.find(".chat-item.type-msg").length;
                while (count > config.maxChatCount) {
                    if (count > config.maxChatCount) {
                        chatBox.children().first().remove();
                        count--;
                    }
                }
            },
            //我方发言
            ownerSend: function (id, msg, anime = true, sendEvent = true) {
                if (!msg) return;

                if (msg.length > context.maxQuesionLength) {
                    return;
                }

                var sendTime = new Date();
                var msgText = msg;

                if (typeof msg == "object") {
                    msgText = msg.content;
                    sendTime = msg.time;
                } else if (typeof msg == "string") {
                    msgText = msg;
                } else {
                    throw new Error("msg type error");
                }

                let tpl = $(doms.tpl_userMsg.html());
                //保留换行符插入
                $(tpl).find(".msg-content").html(tools.escapeHtml(msgText));
                if (anime) $(tpl).find(".bubble").addClass("fadein");
                tools.checkInsertTime(id, sendTime);
                this.getChatBox(id).append(tpl);

                var character = context.findCharacterById(id);

                if (sendEvent) {
                    pager.fireEvent("onSend", {
                        character: character,
                        msg: msgText,
                        time: sendTime,
                        msgDom: tpl,
                        from: 0,
                    });
                }

                return tpl;
            },
            //对方发言
            otherSend: function (id, msg, anime = true, sendEvent = true) {
                if (!msg) return;
                var sendTime = new Date();
                var msgText = msg;

                if (typeof msg == "object") {
                    msgText = msg.content;
                    sendTime = msg.time;
                } else if (typeof msg == "string") {
                    msgText = msg;
                } else {
                    throw new Error("msg type error");
                }
                var character = context.findCharacterById(id);
                let html = mdConverter.makeHtml(msgText);
                let tpl = $(doms.tpl_aiMsg.html());
                tpl.find(".head-img").attr("src", character.headSrc || "./img/aihead.jpg");
                let isbtm = this.isScrollBottom(id);

                var mdbody = $(tpl).find(".markdown-body");
                mdbody.html(html);
                if (anime) {
                    $(tpl).find(".bubble").addClass("fadein");
                }
                tools.checkInsertTime(id, sendTime);
                this.getChatBox(id).append(tpl);

                if (isbtm) {
                    this.scrollBottom(id);
                }

                if (sendEvent) {
                    pager.fireEvent("onSend", {
                        character: character,
                        msg: msgText,
                        time: sendTime,
                        msgDom: tpl,
                        from: 1,
                    });
                }

                //检测编程语言
                let languages = tools.checkCodeLanguagesFromHtml(mdbody);
                if (languages.length > 0) {
                    pager.fireEvent("onCodeLanguage", languages);
                }

                return tpl;
            },
            //插入时间气泡
            insertTime: function (id, time) {
                if (!time) time = new Date();
                //如果time 不是Date类型，则转换为Date类型
                try {
                    time = new Date(time);
                } catch (error) {
                    throw new Error("time is not a Date type");
                }
                var formatDate = "";
                //如果未超过 24 小时 HH:mm 否则 "MM月dd日 HH:mm"
                if (tools.isSameDay(time, new Date())) {
                    formatDate = tools.formatDate(time, "HH:mm");
                } else {
                    formatDate = tools.formatDate(time, "MM月dd日 HH:mm");
                }
                let tpl = $(doms.tpl_timeMsg.html());
                $(tpl).find(".value").text(formatDate);
                this.getChatBox(id).append(tpl);
            },
            //显示对方正在输入
            displayEntering: function (visible) {
                doms.aiName
                    .parent()
                    .find(".entering")
                    .css("visibility", visible ? "visible" : "hidden");
            },
            //清空聊天框
            clearChatBox: function (id) {
                this.getChatBox(id).empty();
            },
        },
        //角色栏
        characterList: {
            //设置最后一条消息时间
            setLastTime(id, sendTime) {
                var character = context.findCharacterById(id);
                var listItemDom = character.characterTarget;
                if (!character) return;
                var formatDate = "";
                if (sendTime) {
                    //如果未超过 24 小时 HH:mm 否则 "MM月dd日 HH:mm"
                    if (tools.isSameDay(sendTime, new Date())) {
                        formatDate = tools.formatDate(sendTime, "HH:mm");
                    } else {
                        formatDate = tools.formatDate(sendTime, "MM月dd日 HH:mm");
                    }
                }

                $(listItemDom).find(".time").text(formatDate);
            },
        },
    };

    //给对象设置事件能力
    tools.setEventAbility(pager, context);

    //绑定事件
    var bindEvent = function () {
        //发送按钮点击事件
        doms.sendBtn.on("click", function () {
            let text = pager.quesionInput.getText();
            if (text.trim() == "") return;

            if (text.replace(/\n/g, "").replace(/\s/g, "").length > context.maxQuesionLength) {
                layer.msg("问题太长啦，精简一下吧");
                return;
            }

            pager.chatBox.ownerSend(context.activeCharacter.id, text);
            //pager.chatBox.otherSend(text);
            pager.quesionInput.clear();
        });

        //清空按钮点击事件
        doms.clearBtn.on("click", function () {
            pager.quesionInput.clear();
        });

        //quesionTextArea 回车发送
        doms.quesionTextArea.on("keydown", function (e) {
            //回车发送
            if (e.keyCode == 13 && !e.shiftKey) {
                doms.sendBtn.click();
                e.preventDefault();
            }
        });

        //输入框输入事件
        doms.quesionTextArea.on("input", function () {
            pager.quesionInput.calcRemLength();
        });

        //回到底部按钮点击事件
        doms.backBtm.on("click", function () {
            pager.chatBox.scrollBottom(context.activeCharacter.id);
        });

        //更多
        doms.more_btn.contextMenu({
            width: 110, // width
            itemHeight: 30, // 菜单项height
            fixPosition: true, // 是否固定位置
            bgColor: "var(--color-menu-bg)", // 背景颜色
            color: "var(--color-menu-color)", // 字体颜色
            fontSize: "0.9em", // 字体大小
            offsetX: -100,
            offsetY: 10,
            hoverBgColor: "var(--color-menu-hover-bg)", // hover背景颜色
            target: function (ele) {
                //当前元素
            },
            menu: [
                {
                    // 菜单项
                    text: "清空会话",
                    icon: "&#xe680",
                    callback: function () {
                        var character = context.activeCharacter;
                        character.clearMessage();
                        pager.chatBox.clearChatBox(character.id);
                        layer.msg("会话上下文已清空");
                        //清理后主动打招呼
                        var welcom = tools.randomOne(character.reConversationMsgList);
                        if (welcom) {
                            setTimeout(function () {
                                pager.chatBox.otherSend(character.id, welcom, true, false);
                            }, 1000);
                        }
                        $.post("/api/ChatApi/ResetConversation", { cid: context.activeCharacter.id });
                    },
                },
                {
                    text: "保存会话",
                    icon: "&#xe936;",
                    callback: function () {
                        var character = context.activeCharacter;
                        if (character.messageList.length == 0) {
                            layer.msg("没有消息可以保存");
                            return;
                        }
                        character.saveMessage();
                        layer.msg("会话已保存");
                    },
                },
            ],
        });

        //检测到代码语言事件
        pager.on("onCodeLanguage", function (languaList) {
            //重新渲染 languaList 中 dom 的高亮
            languaList.forEach(function (item) {
                hljs.highlightBlock(item.dom);

                //找到父级的 pre 标签，添加 .func-btn .copy-btn
                var pre = $(item.dom).parent();
                if (pre[0].tagName.toLowerCase() == "pre") {
                    //复制按钮
                    var button = document.createElement("i");
                    button.className = "func-btn copy-btn";
                    button.innerHTML = "&#xec7a;&nbsp;复制";
                    pre.append(button);

                    //代码code标识
                    var code = document.createElement("span");
                    code.className = "code-name";
                    code.innerHTML = item.lang;
                    pre.append(code);

                    //复制按钮点击事件
                    $(button).on("click", function () {
                        var text = $(item.dom).text();
                        tools.copyText(text);
                        button.innerHTML = "&#xec7a;&nbsp;已复制";
                    });
                }
            });
            var loaded = hljs.listLanguages();
            //排除不存在的语言 和 已经加载的语言
            languaList = languaList.filter(function (item) {
                return hljs.getLanguage(item.lang) && loaded.indexOf(item.lang) < 0;
            });
        });

        //发送事件
        pager.on("onSend", function (data) {
            var character = data.character;
            var msg = data.msg;
            var sendTime = data.time;
            var from = data.from;
            var msgDom = data.msgDom;
            var msgId = tools.nextId();
            //设置好友列表的最后一次发送时间
            pager.characterList.setLastTime(character.id, sendTime);

            //缓存消息
            $(msgDom).data("msgid", msgId).attr("id", "msg-" + msgId);
            var msgEnty = character.pushMessage(msgId, msg, from);

            if (from == 0) {
                //发送请求
                var overd = false;
                $.ajax({
                    url: "/api/ChatApi/Ask",
                    type: "get",
                    data: {
                        cid: character.id,
                        question: msg,
                    },
                    beforeSend: function (res) {
                        setTimeout(function () {
                            if (overd) return;
                            character.entering = true;
                            pager.chatBox.displayEntering(true);
                        }, 1000);
                    },
                    success: function (res) {
                        overd = true;

                        if (!res.success) {
                            tools.setMsgFail(msgDom, msgId);
                            msgEnty.fail = true;
                        }

                        pager.chatBox.otherSend(character.id, res.data);

                        if (context.activeCharacter == character) {
                            pager.chatBox.displayEntering(false);
                            character.entering = false;
                        }
                    },
                    error: function (res) {
                        pager.chatBox.otherSend(character.id, "服务器出现异常:" + res.status);
                        tools.setMsgFail(msgDom, msgId);
                        msgEnty.fail = true;
                    },
                    complete: function (res) {
                        overd = true;
                        if (context.activeCharacter == character) {
                            pager.chatBox.displayEntering(false);
                            character.entering = false;
                        }
                    },
                });

                pager.chatBox.scrollBottom(character.id);
            }
            if (from == 1) {
            }

            //删除超出的消息
            pager.chatBox.checkRemove(character.id);
        });

        //页面加载完毕
        context.on("redy", function () {
            this.characters.forEach(function (item) {
                msg = item.getLastMessage();
                var time = null;
                if (msg) time = msg.time;
                pager.characterList.setLastTime(item.id, time);
            });

            doms.input_maxlen.text(context.maxQuesionLength);
        });

        //会话角色切换
        context.on("activeChange", function (character) {

            pager.chatBox.displayEntering(character.entering);
            doms.aiName.text(character.name);

            //欢迎语
            if (character.messageList.length == 0) {
                var id = character.id;
                var user = character;
                var localWelcome = tools.randomOne(user.welcomeMsgList);
                if (character.welcomeFromAi) {
                    $.ajax({
                        url: "/api/ChatApi/SayHello",
                        type: "get",
                        data: { cid: character.id },
                        success: function (res) {
                            if (res.success) {
                                pager.chatBox.otherSend(character.id, res.data);
                            } else {
                                pager.chatBox.otherSend(character.id, localWelcome);
                            }
                        }
                    });
                } else {
                    setTimeout(function () {
                        if (localWelcome) {
                            pager.chatBox.otherSend(id, localWelcome);
                        }
                    }, 1000);
                }
            }
        });
    };
    bindEvent();

    window.pager = pager;
    window.tools = tools;
    window.pageConfig = config;
    window.pageContext = context;

    class Character {
        mssageCache = []; //消息缓存
        name = ""; //角色名
        id = 0; //角色id
        desc = ""; //角色描述
        icon = ""; //角色图标
        headSrc = ""; //头像地址
        welcomeFromAi = false; //是否从ai获取欢迎语
        entering = false;
        /**欢迎用语候选列表 */
        welcomeMsgList = [];
        /**请空对话框后的主动用语列表*/
        reConversationMsgList = [];

        /**
         * 消息记录
         * @type {Message[]}
         */
        messageList = [];

        /**
         * 左侧角色列表的dom
         * @type {HTMLElement}
         */
        characterTarget = null;

        /**
         * 聊天框dom
         * @type {HTMLElement}
         */
        chatBoxTarget = null;

        constructor(obj) {
            if (!obj) return;
            this.id = obj.id || 0;
            this.name = obj.name || "";
            this.desc = obj.desc || "";
            this.icon = obj.icon || "";
            this.welcomeMsgList = obj.welcomeMsgList || [];
            this.reConversationMsgList = obj.reConversationMsgList || [];
            this.messageList = obj.messageList || [];
            this.headSrc = obj.headSrc || "./img/aihead.jpg";
            this.welcomeFromAi = obj.welcomeFromAi || false;
        }

        /**添加消息 */
        pushMessage(id, msg, from) {
            var enty = new Message();
            enty.from = from;
            enty.content = msg;
            enty.time = new Date();
            enty.id = id;
            while (this.messageList.length > config.maxChatCount) {
                this.messageList.shift();
            }
            this.messageList.push(enty);

            if (config.autoSaveMsg) {
                this.saveMessage();
            }

            return enty;
        }

        /**保存消息 */
        saveMessage() {
            //保存消息
            var msg = JSON.stringify(this.messageList);
            localStorage.setItem("character_msgs_" + this.id, msg);
        }

        /**清空消息 */
        clearMessage() {
            this.messageList = [];
            this.saveMessage();
        }

        /**读取消息*/
        loadMessageFromLocal() {
            var msg = localStorage.getItem("character_msgs_" + this.id);
            if (!msg) return;
            if (msg) {
                this.messageList = JSON.parse(msg);
            }
            //按照时间排序
            this.messageList.sort(function (a, b) {
                return a.time - b.time;
            });
        }

        /**获取最后一条消息 */
        getLastMessage(from) {
            if (this.messageList.length == 0) return null;
            if (!from) {
                return this.messageList[this.messageList.length - 1];
            }
            else {
                for (var i = this.messageList.length - 1; i >= 0; i--) {
                    if (this.messageList[i].from == from) {
                        return this.messageList[i];
                    }
                }
            }
            return null;
        }

        /**根据id获取消息 */
        getMessageById(id) {
            for (var i = 0; i < this.messageList.length; i++) {
                if (this.messageList[i].id == id) {
                    return this.messageList[i];
                }
            }
            return null;
        }
    }

    Character.prototype.clearLocalMessage = function (existIds) {
        //遍历 localStorage
        for (var i = 0; i < localStorage.length; i++) {
            var key = localStorage.key(i);
            if (key.indexOf("character_msgs_") == 0) {
                var id = parseInt(key.split("_")[2]);
                if (existIds.indexOf(id) < 0) {
                    localStorage.removeItem(key);
                }
            }
        }
    };

    class Message {
        id = 0; //消息id
        from = 0; //消息来源 0:自己 1:对方 2:系统
        time = new Date(); //消息时间
        content = ""; //消息内容
        fail = false; //是否发送失败
    }
});
